package com.lp.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.lp.annotation.Code;
import com.lp.annotation.CodeAnnotationBean;
import com.lp.bo.ProDictionaryInfoBO;
import com.lp.cache.CacheName;
import com.lp.cache.ProCacheUtil;
import com.lp.common.Constants.CodeType;
import com.lp.dao.BaseDao;
import com.lp.util.LogUtil;
import com.lp.util.ObjectUtil;
import com.lp.util.PageBean;
import com.lp.util.ResultMapUtils;

/**
 * 数据访问基类
 * 
 */
@Component("baseDao")
public class BaseDaoImpl extends ResultMapUtils implements BaseDao {

	private static final long serialVersionUID = -7740327382630707675L;
	/**
	 * LOG
	 */
	protected final static Logger LOGGER = LoggerFactory.getLogger(BaseDaoImpl.class);
	
	@Autowired
	protected SqlSession sqlSession;

	@Override
	public Integer selectCount(String statement, Object param) {
		return sqlSession.selectOne(statement, param);
	}

	@Override
	public int insert(String statement, Object param) {
		return sqlSession.insert(statement, param);
	}
	
	@Override
	public Integer update(String statement, Object param) {
		return sqlSession.update(statement, param);
	}
	
	@Override
	public Integer delete(String statement, Object param) {
		return sqlSession.delete(statement, param);
	}

	@Override
	public <T> List<T> selectList(String statement, Object obj, PageBean pageBean)  {
		List<T> o = null ;
		try {
			pageBean.setPageParam4Mysql(obj);
			o = sqlSession.selectList(statement, obj);
			setAnnotation4Select(o);
		} catch (Exception e) {
			LogUtil.errorLog(e);
		}
		return o;
	}

	@Override
	public <T> T selectOne(String statement, Object obj) {
		T a = sqlSession.selectOne(statement, obj);
		setAnnotation4Select(a);
		return a ;
	}

	@Override
	public <T> List<T> selectList(String statement, Object obj) {
		List<T> a = sqlSession.selectList(statement,obj);
		setAnnotation4Select(a);
		return a ;
	}
	
	
	/**
	 * 
	 * 设置名称
	 * 
	 * @param obj
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void setAnnotation4Select(Object obj) {
		try {
			if (obj == null) {
				return;
			}
			List data = null;
			if (!(obj instanceof List)) {
				data = new ArrayList<>();
				data.add(obj);
			} else {
				data = (List) obj;
			}
			if (data.size() > 0) {
				Class clss = data.get(0).getClass();
				// 父类的字段
				Field[] superFields = clss.getSuperclass().getDeclaredFields();
				// 子类的字段
				Field[] fields = clss.getDeclaredFields();
				// 数据字典
				Set<CodeAnnotationBean> dictFieldsSetBean = new HashSet<>();
				for (int i = 0; i < superFields.length; i++) {
					Field f = superFields[i];
					if (f.isAnnotationPresent(Code.class)) {
						Code v = f.getAnnotation(Code.class);
						dictFieldsSetBean.add(new CodeAnnotationBean(f, v.type()));
					}
				}
				//
				for (int i = 0; i < fields.length; i++) {
					Field f = fields[i];
					if (f.isAnnotationPresent(Code.class)) {
						Code v = f.getAnnotation(Code.class);
						dictFieldsSetBean.add(new CodeAnnotationBean(f, v.type()));
					}
				}
				//
				boolean dictFieldFlag = dictFieldsSetBean.size() > 0;
				if (dictFieldFlag) {
					Field l_data_f = null;
					try {
						l_data_f = clss.getField("data");
					} catch (Exception e) {}
					for (Object o : data) {
						Class c = o.getClass();
						Field.setAccessible(c.getDeclaredFields(), true);
						l_data_f.setAccessible(true);
						Map<String, String> annotationedFieldMap = new HashMap<String, String>();
						// 数据字典
						for (CodeAnnotationBean f : dictFieldsSetBean) {
							Method getMethod = c.getMethod("get" + ObjectUtil.upFirstChar(f.getField().getName()), new Class[] {});
							Object key = getMethod.invoke(o, new Object[] {});
							if ( ObjectUtil.isNotEmpty(key) ) {
								// 如果是用字符串的多个数据字典  // key.toString().contains(",")
								if (key instanceof String) {
									String[] keys = key.toString().split(",");
									String code_name = StringUtils.EMPTY;
									for (String k : keys) {
										// 如果是整型值
										Integer dict_key = ObjectUtil.parseIntData(k);
										if (dict_key != -1) {
											ProDictionaryInfoBO pro = ProCacheUtil.getCache(CacheName.DICTIONARY, dict_key.toString() ); 
											if (ObjectUtil.isNotEmpty(pro)) {
												String kn = pro.getName();
												if (StringUtils.isNotEmpty(code_name)) {
													code_name = code_name + "," + kn;
												} else {
													code_name = kn;
												}
											}
										}
									}
									annotationedFieldMap.put(f.getField().getName(), code_name);
									//
								}else if(key instanceof List<?>  ){
									// 倒插
									setAnnotation4Select(key);
								} else if(key instanceof Integer) {
									// 如果是整型值
									Integer dict_key = ObjectUtil.parseIntData(key);
									if (dict_key != -1) {
										if(ObjectUtil.isNotEmpty( ProCacheUtil.getCache(CacheName.DICTIONARY, dict_key.toString(), new ProDictionaryInfoBO()))){
											// 如果需要获取数据字典的值，则进行分支
											if(f.getType() == CodeType.DICTIONARY_VALUE){
												// 这边是硬编码，把单位计算出来
												com.lp.bean.ProDictionaryInfo proDict = ProCacheUtil.getCache(CacheName.DICTIONARY, dict_key.toString(), new ProDictionaryInfoBO());
												if( ObjectUtil.isNotEmpty(proDict.getValue())){
													String value = proDict.getValue();
													Method method = c.getMethod("getSdata" );
													Object valueSdata = method.invoke(o);
													if(ObjectUtil.isEmpty(valueSdata)){
														valueSdata = -1 ;
													}
													String code_value =null ;
													try{
														code_value = ObjectUtil.dictionaryValue( Double.parseDouble(String.valueOf(valueSdata)), value);
														annotationedFieldMap.put(f.getField().getName(), code_value);	
													}catch(NumberFormatException e){
														
													}
													annotationedFieldMap.put(f.getField().getName()+"_value", value);
												}else{
													String code_name = ProCacheUtil.getCache(CacheName.DICTIONARY, dict_key.toString(), new ProDictionaryInfoBO()).getName() ;
													if (ObjectUtil.isNotEmpty(code_name)) {
														annotationedFieldMap.put(f.getField().getName(), code_name);
													}		
												}
											}else{
												String code_name = ProCacheUtil.getCache(CacheName.DICTIONARY, dict_key.toString(), new ProDictionaryInfoBO()).getName(); ;
												if (ObjectUtil.isNotEmpty(code_name)) {
													annotationedFieldMap.put(f.getField().getName(), code_name);
												}												
											}
										}
									}
								}else {
									setAnnotation4Select(key);
								}
							}
						}
						l_data_f.set(o, annotationedFieldMap);
					}
				}
			}
		} catch (Exception e) {
			LogUtil.errorLog(e);
		}
	}
	
}
